package at.codejedi.sto.gui;

import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeListener;

import at.codejedi.sto.config.Configuration;
import at.codejedi.sto.gui.combat.ICombatLogView;

public class MainFrame extends JFrame implements IMainView {

	public static final String fileName = "sto-combat-analyser-main-frame.prop";

	private static final long serialVersionUID = 8332710934267655530L;

	/**
	 * @param window
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void enableOSXFullscreen(Window window) {
		if (window == null)
			return;
		try {
			Class util = Class.forName("com.apple.eawt.FullScreenUtilities");
			Class params[] = new Class[] { Window.class, Boolean.TYPE };
			Method method = util.getMethod("setWindowCanFullScreen", params);
			method.invoke(util, window, true);
		} catch (ClassNotFoundException e1) {
		} catch (Exception e) {

		}
	}

	/** Restore location & size of UI */
	public static void restoreOptions(Frame f) throws IOException {
		File file = Configuration.getPropertyFile(fileName);
		Properties p = new Properties();
		BufferedReader br = new BufferedReader(new FileReader(file));
		p.load(br);

		int x = Integer.parseInt(p.getProperty("x"));
		int y = Integer.parseInt(p.getProperty("y"));
		int w = Integer.parseInt(p.getProperty("w"));
		int h = Integer.parseInt(p.getProperty("h"));

		Rectangle r = new Rectangle(x, y, w, h);

		f.setBounds(r);
	}

	/** Store location & size of UI */
	public static void storeOptions(Frame f) throws Exception {
		File file = Configuration.getPropertyFile(fileName);
		Properties p = new Properties();
		// restore the frame from 'full screen' first!
		f.setExtendedState(Frame.NORMAL);
		Rectangle r = f.getBounds();
		int x = (int) r.getX();
		int y = (int) r.getY();
		int w = (int) r.getWidth();
		int h = (int) r.getHeight();

		p.setProperty("x", "" + x);
		p.setProperty("y", "" + y);
		p.setProperty("w", "" + w);
		p.setProperty("h", "" + h);

		BufferedWriter br = new BufferedWriter(new FileWriter(file));
		p.store(br, "Properties of the user frame");
	}

	JMenuItem clipboardMenu;
	JMenuItem closeMenu;
	JMenuItem createBuild;
	JMenuItem openCombatLogFileMenuItem;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * at.frima.sto.gui.IMainView#openCombatLogFile(java.awt.event.ActionListener
	 * )
	 */

	private List<ActionListener> recentFileSelectedActionListeners = new ArrayList<ActionListener>();

	JMenu recentFilesMenu;

	JTabbedPane tabbedPane;

	private List<ActionListener> windowClosingListeners = new ArrayList<ActionListener>();

	public MainFrame() {
		initUI();
	}

	@Override
	public void addCloseDetailsActionListener(ActionListener l) {
		closeMenu.addActionListener(l);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see at.frima.sto.gui.IMainView#AddCombatLogView(java.lang.String,
	 * javax.swing.JPanel)
	 */
	@Override
	public void addCombatLogView(String name, ICombatLogView combatLogView) {
		tabbedPane.addTab(name, combatLogView.getPanel());

		int index = tabbedPane.indexOfComponent(combatLogView.getPanel());

		tabbedPane.setTabComponentAt(index, new ButtonTabComponent(tabbedPane,
				combatLogView));

	}

	@Override
	public void addRecentFileSelectedActionListener(ActionListener l) {
		recentFileSelectedActionListeners.add(l);
	}

	@Override
	public void addWindowClosingActionListener(ActionListener l) {
		windowClosingListeners.add(l);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see at.frima.sto.gui.IMainView#chooseCombatFilePath()
	 */
	@Override
	public File chooseCombatFilePath() {
		return chooseCombatFilePath(null);
	}

	@Override
	public File chooseCombatFilePath(File startPath) {
		// Create a file chooser
		JFileChooser fc;
		if (startPath != null)
			fc = new JFileChooser(startPath);
		else
			fc = new JFileChooser();
		int returnVal = fc.showOpenDialog(this);

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			File file = fc.getSelectedFile();
			return file;
		}
		return null;
	}

	@Override
	public void closeDetails(boolean enabled) {
		closeMenu.setEnabled(enabled);

	}

	@Override
	public void copyDetailsToClipboard(ActionListener l) {
		clipboardMenu.addActionListener(l);
	}

	@Override
	public void copyDetailsToClipboard(boolean enabled) {
		clipboardMenu.setEnabled(enabled);
	}

	private void createMenuBar() {
		// Where the GUI is created:
		JMenuBar menuBar;
		JMenu fileMenu;

		// Create the menu bar.
		menuBar = new JMenuBar();

		// Build the first menu.
		fileMenu = new JMenu(Configuration.getLabel("File"));
		fileMenu.setMnemonic(KeyEvent.VK_F);
		fileMenu.getAccessibleContext().setAccessibleDescription(
				Configuration.getLabel("FileMenu"));
		menuBar.add(fileMenu);

		// a group of JMenuItems
		openCombatLogFileMenuItem = new JMenuItem(
				Configuration.getLabel("Open"), KeyEvent.VK_T);
		openCombatLogFileMenuItem.setAccelerator(KeyStroke.getKeyStroke(
				KeyEvent.VK_O, ActionEvent.CTRL_MASK));
		openCombatLogFileMenuItem.getAccessibleContext()
				.setAccessibleDescription(
						Configuration.getLabel("CombatLogOpen"));
		fileMenu.add(openCombatLogFileMenuItem);

		fileMenu.addSeparator();

		recentFilesMenu = new JMenu(Configuration.getLabel("RecentFile"));
		recentFilesMenu.getAccessibleContext().setAccessibleDescription(
				"Recent opened files");
		fileMenu.add(recentFilesMenu);
		fileMenu.addSeparator();

		JMenuItem exitMenuItem = new JMenuItem(Configuration.getLabel("Quit"));
		exitMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
				ActionEvent.CTRL_MASK));
		exitMenuItem.getAccessibleContext().setAccessibleDescription(
				"Closes the Application");
		final JFrame frame = this;
		exitMenuItem.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				requestExit(frame);
			}
		});
		fileMenu.add(exitMenuItem);

		JMenu logMenu = new JMenu(Configuration.getLabel("Log"));
		logMenu.setMnemonic(KeyEvent.VK_M);
		logMenu.getAccessibleContext().setAccessibleDescription(
				Configuration.getLabel("LogMenu"));
		menuBar.add(logMenu);

		clipboardMenu = new JMenuItem(Configuration.getLabel("CopyToClipboard"));
		clipboardMenu.setEnabled(false);
		clipboardMenu.getAccessibleContext().setAccessibleDescription(
				Configuration.getLabel("CopyToClipboardDesc"));
		logMenu.add(clipboardMenu);

		closeMenu = new JMenuItem(Configuration.getLabel("CloseCurrentTab"));
		closeMenu.setEnabled(false);

		closeMenu.getAccessibleContext().setAccessibleDescription(
				Configuration.getLabel("CloseCurrentTabDesc"));
		logMenu.add(closeMenu);

		createBuild = new JMenuItem(Configuration.getLabel("CreateBuild"));
		createBuild.setEnabled(false);
		createBuild.getAccessibleContext().setAccessibleDescription(
				Configuration.getLabel("CreateBuildDesc"));
		logMenu.add(createBuild);

		JMenu helpmenu = new JMenu("?");
		menuBar.add(helpmenu);

		JMenuItem aboutMenuItem = new JMenuItem(Configuration.getLabel("About"));

		aboutMenuItem.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				AboutDialog aboutDialog = new AboutDialog();
				aboutDialog.setLocationRelativeTo(frame);
				aboutDialog.setVisible(true);

			}
		});
		helpmenu.add(aboutMenuItem);

		setJMenuBar(menuBar);
	}

	@Override
	public void createShipBuild(ActionListener l) {
		createBuild.addActionListener(l);
	}

	public void enableOSXSpecialFeatures() {
		enableOSXFullscreen(this);
	}

	public final void initUI() {
		ImageIcon fullIcon = Configuration.getFullIcon();
		if (fullIcon != null) {
			Image image = fullIcon.getImage();
			setIconImage(image);
		}
		createMenuBar();

		GridLayout layout = new GridLayout(1, 1);
		setLayout(layout);
		tabbedPane = new JTabbedPane();

		add(tabbedPane);

		setTitle("STO Combat Analyser");
		setSize(600, 600);
		setLocationRelativeTo(null);
	}

	@Override
	public void openCombatLogFile(ActionListener l) {
		openCombatLogFileMenuItem.addActionListener(l);
	}

	@Override
	public void persistCombatLogEnabled(boolean enabled) {
		createBuild.setEnabled(enabled);
	}

	@Override
	public void removeCombatLogView(ICombatLogView combatLogView) {
		tabbedPane.remove(combatLogView.getPanel());
	}

	private void requestExit(final JFrame frame) {
		try {
			storeOptions(frame);
			for (ActionListener l : windowClosingListeners) {
				l.actionPerformed(new ActionEvent(this, 0, null));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.exit(0);
	}

	@Override
	public void selectOpenCombatLogFile(ChangeListener l) {
		tabbedPane.addChangeListener(l);
	}

	@Override
	public void setRecentFilesList(List<File> files) {
		recentFilesMenu.removeAll();
		for (File f : files) {
			JMenuItem recentFileItem = new JMenuItem(f.getName());
			recentFilesMenu.add(recentFileItem);
			recentFileItem.setActionCommand(f.getAbsoluteFile().toString());
			recentFileItem.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					String filePath = arg0.getActionCommand();
					for (ActionListener l : recentFileSelectedActionListeners) {
						l.actionPerformed(new ActionEvent(arg0.getSource(), 0,
								filePath));
					}
				}
			});

		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see at.frima.sto.gui.IMainView#ShowException(java.lang.Throwable)
	 */
	@Override
	public void showException(Throwable t) {
		JOptionPane.showMessageDialog(this, t.getMessage(),
				"Ups, something happend...", JOptionPane.ERROR_MESSAGE);
	}

	@Override
	public void showInfo(String title, String message) {
		JOptionPane.showMessageDialog(this, message, title,
				JOptionPane.WARNING_MESSAGE);

	}

	@Override
	public void showView() {
		setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
		final JFrame frame = this;
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent we) {
				requestExit(frame);
			}
		});

		File file = Configuration.getPropertyFile(fileName);
		if (file.exists()) {
			try {
				restoreOptions(this);
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}
		} else {
			setLocationByPlatform(true);
		}
		enableOSXSpecialFeatures();
		setVisible(true);
	}

	@Override
	public void showWarning(String title, String message) {
		JOptionPane.showMessageDialog(this, message, title,
				JOptionPane.WARNING_MESSAGE);

	}
}
